package com.azh.server.tables;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

import com.azh.server.util.ExceptionUtils;
import com.azh.server.util.FileCommonUtils;

/**
 * @author zhaozhenhang <zhaozhenhang@kuaishou.com>
 * Created on 2022-05-01
 * 启动类，管理AeroDB启动信息, 记录第一个表的uid
 */
public class Bootstarter {

    public static final String bootstarter_suffix = ".at";

    public static final String bootstarter_tmp_suffix = ".at_tmp";

    String path;

    File file;

    public Bootstarter(String path, File file) {
        this.path = path;
        this.file = file;
    }

    public static Bootstarter create(String path) {
        removeBadTmp(path);
        File f = new File(path + bootstarter_suffix);
        try {
            if (!f.createNewFile()) {
                ExceptionUtils.getMessage(new RuntimeException("File already exists!"));
            }
        } catch (Exception e) {
            ExceptionUtils.getMessage(e);
        }
        if (FileCommonUtils.canReadOrWrite(f)) {
            ExceptionUtils.getMessage(new RuntimeException("File cannot read or write!"));
        }
        return new Bootstarter(path, f);
    }

    public static Bootstarter open(String path) {
        removeBadTmp(path);
        File f = new File(path + bootstarter_suffix);
        if (!f.exists()) {
            ExceptionUtils.getMessage(new RuntimeException("File does not exists!"));
        }
        if (FileCommonUtils.canReadOrWrite(f)) {
            ExceptionUtils.getMessage(new RuntimeException("File cannot read or write!"));
        }
        return new Bootstarter(path, f);
    }

    public byte[] load() {
        byte[] buffer = null;
        try {
            buffer = Files.readAllBytes(file.toPath());
        } catch (IOException e) {
            ExceptionUtils.getMessage(e);
        }
        return buffer;
    }

    /**
     * update 修改at文件内容时，，没有直接修改at文件，而是将内容吸写入一个at_tmp文件中，
     * 然后将这个文件命名为at文件，痛殴操作系统重命名保证文件的原子性，间接保证操作系统原子性.
     * @param data
     */
    public void update(byte[] data) {
        File temp = new File(path + bootstarter_tmp_suffix);
        try {
            temp.createNewFile();
        } catch (Exception e) {
            ExceptionUtils.getMessage(e);
        }
        if (FileCommonUtils.canReadOrWrite(temp)) {
            ExceptionUtils.getMessage(new RuntimeException("File cannot read or write!"));
        }
        try (FileOutputStream out = new FileOutputStream(temp)) {
            out.write(data);
            out.flush();
        } catch (IOException e) {
            ExceptionUtils.getMessage(e);
        }
        try {
            Files.move(temp.toPath(), new File(path + bootstarter_suffix).toPath(),
                    StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            ExceptionUtils.getMessage(e);
        }
        file = new File(path + bootstarter_suffix);
        if (FileCommonUtils.canReadOrWrite(file)) {
            ExceptionUtils.getMessage(new RuntimeException("File cannot read or write!"));
        }
    }

    private static void removeBadTmp(String path) {
        new File(path + bootstarter_tmp_suffix).delete();
    }

}
